home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************
- *
- * f6.ca: special routines for screen dump ops:
- * part 1 of 3.
- *
- *
- ******************************************************************/
-
-
- /****
- *
- * explode-- generate a list of scan-line slices from the contents of
- * a character cell.
- *
- * also calculate and return hash value for
- * the pattern processed.
- *
- * WARNING: 'explode' must be used on font forms only.
- *
- * at entry:
- * (a6) + 8 -> ascii code of char to explode.
- * (a6) + 12 -> pointer to font header desired.
- * (a6) + 16 -> area in which to save scan line values.
- *
- * at exit:
- * returns hash value in d7,
- * next 'scan_pack' space in a0.
- * all other registers preserved.
- *
- *
- ****/
- explode:
- link A6,#0 ;frame pointer
- movem.l D0-D6/A1-A5,-(A7) ;save everything
-
- movea.l 16(A6),A1 ;pointer for storing scan lines
- movea.l 12(A6),A5 ;get font header pointer
- move.l 8(A6),D5 ;ascii code of char
- move.l #0,D1 ;clear registers-- quickly
- move.l #0,D2
- move.l #0,D3
- move.l #0,D4
- move.l #0,D6
- move.l #0,D7
-
- movea.l CHAR_OFFTAB(A5),A4 ;get base of char offset table
- move.w FORM_HEIGHT(A5),D2 ;get char height (scan lines)
- movea.l FONT_DATA(A5),A0 ;get start of actual font data
- move.w FORM_WIDTH(A5),D1 ;get scan line length
- move.w BIG_WIDTH(A5),D4 ;get char (vice char cell) width
-
- lsl.l #1,D5 ; * 2 for word index
- move.w 0(A4,D5.l),D3 ;get char offset val
-
- /* now calculate char position in bit table */
- divu #BYTESIZE,D3 ;offset / bytesize in d3.w
- move.w D3,-(A7) ;save it
- move.w #0,-(A7) ;make it a long when it comes back
- lsr.l #BYTESIZE,D3
- lsr.l #BYTESIZE,D3 ;offset % bytesize in d3.w
- adda.l (A7)+,A0 ;get byte address in font data
-
- /* a0 == byte address in font data table, d3 == bit offset, if any */
- /* now calculate char mask into d5 */
- clr.l D5 ;clear mask reg
- move.l #-1,-(A7) ;no invert
- bsr slice_and_hash ;get slices and hash values
- addq.l #4,A7 ;pop arg
- movea.l A1,A0 ;return scan pack next pointer
-
- movem.l (A7)+,D0-D6/A1-A5 ;restore registers
- unlk A6 ;deallocate frame pointer
- rts
-
-
- /****
- *
- * hash_char-- count each set pixel in a char cell, assigning to
- * each pixel a unique number based on matrix position
- * in the cell.
- *
- * at entry:
- * d0.b == char data
- * d2 == current scan line (counting down)
- * d4 == char width
- *
- * at exit:
- * d7 == intermediate hash value
- * all other registers preserved
- *
- *
- ****/
- hash_char:
- movem.l D0-D3/D4,-(A7) ;save registers
-
- mulu D4,D2 ;width * line == hash base
- clr.l D1 ;hash counter
- clr.l D3 ;running total
- bra.s hash_test ;start
- hash_loop:
- addq.l #1,D1 ;inc counter
- lsl.b #1,D0 ;get a bit
- bcc.s hash_test ;if zero, continue
- move.l D2,-(A7) ;else save hash base
- add.l D1,D2 ;get unique number this bit
- add.l D2,D3 ;add to total
- move.l (A7)+,D2 ;restore hash base
- hash_test:
- dbf D4,hash_loop ;get all the data
-
- move.l D3,D7 ;save result
-
- movem.l (A7)+,D0-D3/D4 ;restore registers
- rts
-
-
- /****
- *
- * setup_hash-- set up hash table for a given font.
- *
- * at entry:
- * (a6) + 8 -> font header pointer.
- *
- * at exit:
- * all registers preserved.
- *
- *
- ****/
- setup_hash:
- link A6,#0 ;frame pointer
- movem.l A0-A2/A4/D0/D7,-(A7) ;save registers
- move.l #-1,D0 ;get a4
- bsr reg_a4 ;do it
- movea.l scan_packs(A4),A2 ;start of collision space
- movea.l hash_table(A4),A1 ;start of hash table
- move.l #0,D0 ;first ascii code
-
- s_hash_loop:
- move.l #-1,(A2) ;init 'next' fld this pack
- pea 6(A2) ;push data part this pack
- move.l 8(A6),-(A7) ;font header pointer
- move.l D0,-(A7) ;ascii code
- bsr explode ;get hash val, &c.
- adda.l #12,A7 ;pop args
-
- /* d7 == hash val */
- /* a0 == next free 'scan_packs' space, if needed */
- mulu #HASH_IX,D7 ;get hash index
- tst.l 2(A1,D7.l) ;test 'use' field
- bmi not_used ;if not used
- move.l D0,-(A7) ;else push ascii code
- pea 0(A1,D7.l) ;push 'hash_table' pos
- move.l A2,-(A7) ;push 'scan_pack' address
- bsr collide ;insert into collision list
- adda.l #12,A7 ;pop args
- movea.l A0,A2 ;next 'scan_pack' space
- bra hash_next ;and continue
- not_used:
- move.w D0,0(A1,D7.l) ;store code
- move.l #NULL,2(A1,D7.l) ;but no collision list yet
-
- hash_next:
- addq.l #1,D0 ;next ascii code
- cmp.l #HASH_SIZE,D0 ;finished?
- beq.s hash_exit ;if so
- bra s_hash_loop ;else continue
- hash_exit:
- movem.l (A7)+,A0-A2/A4/D0/D7 ;restore registers
- unlk A6 ;deallocate frame
- rts
-
-
- /****
- *
- * collide-- insert pointer to 'scan_pack' into the collision list
- * of a hash table element or begin the collision list.
- *
- * at entry:
- * (a6) + 8 -> 'scan_pack' address.
- * (a6) + 12 -> 'hash_table' element address.
- * (a6) + 16 -> ascii code.
- *
- * at exit:
- * all registers preserved.
- *
- *
- ****/
- collide:
- link A6,#0 ;frame pointer
- movem.l A0-A1/D0,-(A7) ;save registers
-
- move.l 16(A6),D0 ;get ascii code
- movea.l 8(A6),A0 ;'scan_pack' address
- movea.l 12(A6),A1 ;'hash_table' element address
- tst.l 2(A1) ;test 'use' field
- bne add_list ;if list already started
- move.l A0,2(A1) ;else insert pointer to 'scan_pack'
- move.w D0,4(A0) ;store ascii code
- bra collide_exit ;and leave
-
- add_list:
- movea.l 2(A1),A1 ;get pointer to head of list
- looking:
- tst.l (A1) ;test 'next' field
- bmi found_it ;if == -1, then end found
- movea.l (A1),A1 ;else get next pointer
- bra looking ;and keep going
- found_it:
- move.l A0,(A1) ;insert pointer to 'scan_pack'
- move.w D0,4(A0) ;store ascii code into 'scan_pack'
- collide_exit:
- movem.l (A7)+,A0-A1/D0 ;restore registers
- unlk A6 ;deallocate frame
- rts
-
-
- /****
- *
- * find_collide-- find a matching set of scan lines in a collision list.
- *
- * at entry:
- * (a6) + 8 -> first 'scan_pack' pointer.
- * (a6) + 12 -> scan line list to be matched.
- *
- * at exit:
- * d0 contains ascii code of matched character, or 0
- * if error.
- *
- *
- ****/
- find_collide:
- link A6,#0 ;frame pointer
- movem.l D1-D3/A0-A1,-(A7) ;save registers
-
- movea.l 8(A6),A0 ;'scan_pack' list
- movea.l 12(A6),A1 ;scan line list address
-
- collide_loop:
- move.l A0,D2 ;save base pointer
- lea.l 6(A0),A0 ;get start of data
- find_c_loop:
- cmpm.b (A0)+,(A1)+ ;compare lines
- bne c_no_match ;no match => go to next
- cmpi.b #BORDER,(A0) ;end of data?
- beq c_good_match ;if so
- bra find_c_loop ;else keep going
- c_no_match:
- movea.l D2,A0 ;recover base pointer
- tst.l (A0) ;was that the last one?
- bmi f_coll_error ;if so
- movea.l (A0),A0 ;else get pointer
- movea.l 12(A6),A1 ;reset scan list pointer
- bra collide_loop ;and continue
-
- c_good_match:
- movea.l D2,A0 ;recover base pointer
- clr.l D0
- move.w 4(A0),D0 ;get ascii code
-
- f_coll_exit:
- movem.l (A7)+,D1-D3/A0-A1 ;restore registers
- unlk A6 ;deallocate frame
- rts
-
- f_coll_error:
- move.l #0,D0 ;error code
- bra f_coll_exit ;and leave
-
-
- /****
- *
- * match_lists-- compare two scan lists.
- *
- * at entry:
- * (a6) + 8 -> one scan list.
- * (a6) + 12 -> the other scan list.
- *
- * at exit:
- * d0 contains -1 if no match; else 1.
- *
- *
- ****/
- match_lists:
- link A6,#0 ;frame pointer
- movem.l A0-A1,-(A7)
-
- movea.l 8(A6),A0 ;one cell list
- movea.l 12(A6),A1 ;the other list
- zm_l_loop:
- cmpm.b (A0)+,(A1)+ ;compare one line
- bne zm_l_nomatch
- cmpi.b #BORDER,(A0) ;end of data?
- beq zm_l_goodmatch ;if so
- bra zm_l_loop
- zm_l_nomatch:
- move.l #-1,D0 ;fail code
- bra zm_l_exit ;and leave
- zm_l_goodmatch:
- move.l #1,D0 ;success code
- zm_l_exit:
- movem.l (A7)+,A0-A1
- unlk A6
- rts
-
-
- /****
- *
- * make_slices-- from a byte address and a bit offset, return the
- * contents of the current char cell in the form of
- * a list of scan-line values, and calculate a hash
- * value.
- *
- * at entry:
- * (a6) + 8 -> byte address of current cell.
- * (a6) + 12 -> font header.
- * (a6) + 16 -> area in which to save scan line data.
- * (a6) + 20 -> bit offset.
- * (a6) + 24 -> scan line length.
- * (a6) + 28 -> invert flag.
- *
- * at exit:
- * d0 == 0 if no set pixels in this cell, else != 0.
- * d7 == hash value.
- * all other registers preserved.
- *
- *
- ****/
- make_slices:
- link A6,#0 ;frame pointer
- movem.l D1-D6/A0-A1/A4/A5,-(A7)
-
- movea.l 8(A6),A0 ;cell address
- movea.l 12(A6),A5 ;font header
- movea.l 16(A6),A1 ;save area
-
- move.l #0,D1 ;clear registers quickly
- move.l #0,D2
- move.l #0,D3
- move.l #0,D4
- move.l #0,D5
- move.l #0,D6
- move.l #0,D7
-
- move.w FORM_HEIGHT(A5),D2 ;char height
- move.l 24(A6),D1 ;scan length
- move.w BIG_WIDTH(A5),D4 ;char width
- move.l 20(A6),D3 ;bit offset
-
- move.l 28(A6),-(A7) ;push invert flag
- bsr slice_and_hash ;get slices and hash value
- addq.l #4,A7 ;pop arg
-
- move.l D6,D0 ;return flag
- movem.l (A7)+,D1-D6/A0-A1/A4/A5
- unlk A6
- rts
-
-
- /****
- *
- * slice_and_hash-- generate a list of scan-line slices from a memory
- * cell and calculate a hash value for the list.
- * (called by 'explode' and 'make_slices').
- *
- * at entry:
- * (a6) + 8 -> invert flag: 0 => invert, else don't.
- *
- * (a0) -> start of data cell.
- * (a1) -> start of list storage area.
- *
- * d0 is cleared (receives char data).
- * d1 == scan length.
- * d2 == scan line count (char height).
- * d3 == bit offset of data cell.
- * d4 == char width.
- * d5 is cleared (used for char data mask).
- * d6 is cleared (used for pixel-set flag).
- * d7 is cleared (used for hash value).
- *
- * at exit:
- * (a1) -> next byte after scan list space used.
- * d6 == 0 if no set pixels this cell, else != 0.
- * d7 == hash value.
- *
- *
- ****/
- slice_and_hash:
- link A6,#0 ;frame pouinter
- clr.l D6 ;clear pixel-set flag
- bra m_sl_test ;now go
-
- m_sl_loop:
- clr.l D0
- move.b 0(A0),D0 ;get byte
- tst.l 8(A6) ;invert?
- bne.s h_s_next ;if not
- not.b D0 ;else take one's complement
-
- h_s_next:
- move.b D0,(A1)+ ;save it
-
- move.l D7,-(A7) ;save current hash val
- bsr hash_char ;calc intermediate val
- add.l (A7)+,D7 ;add to total
-
- tst.b D0 ;test for set pixels
- beq.s m_sl_nxt ;if no set pixels
- move.l #1,D6 ;else set flag
- m_sl_nxt:
- adda.l D1,A0 ;next line
- m_sl_test:
- dbf D2,m_sl_loop ;continue
-
- /* WARNING: '.w' length used here to cheat on address alignment-- */
- /* value of d2 above should be explicitly checked to see if this */
- /* is necessary */
- move.b #BORDER,(A1)+ ;end marker
- move.b #BORDER,(A1)+ ;aligned
- divu #HASH_SIZE,D7 ;finalize hash value
- lsr.l #BYTESIZE,D7
- lsr.l #BYTESIZE,D7
- unlk A6 ;deallocate frame
- rts ;dummy comment
-
-
-
-
-
-